Skip to main content

Memory Addressing

Modern x86 processors can address up to 2^32 bytes of memory, which means memory addresses are represented on 32 bits. To address memory, the processor uses addresses (implicitly, each label is translated into a corresponding memory address). Besides labels, there are other forms of addressing memory:

mov eax, [0xcafebab3]         ; direct (displacement)
mov eax, [esi] ; indirect (base)
mov eax, [ebp-8] ; based (base + displacement)
mov eax, [ebx*4 + 0xdeadbeef] ; indexed (index * scale + displacement)
mov eax, [edx + ebx + 12] ; based and indexed without scale (base + index + displacement)
mov eax, [edx + ebx*4 + 42] ; based and indexed with scale (base + index * scale + displacement)

WARNING: The following addressing modes are invalid:

mov eax, [ebx-ecx]     ; Registers can only be added
mov [eax+esi+edi], ebx ; The address calculation can involve at most 2 registers

Size Directives

Generally, the size of a value brought from memory can be inferred from the instruction code used. For example, in the above addressing modes, the size of the values could be inferred from the size of the destination register, but in some cases, this is not so obvious. Let's consider the following instruction:

mov [ebx], 2

As seen, it intends to store the value 2 at the address contained in the ebx register. The size of the register is 4 bytes. The value 2 can be represented on both 1 and 4 bytes. In this case, since both interpretations are valid, the processor needs additional information on how to treat this value. This can be done through size directives:

mov byte [ebx], 2  ; Move the value 2 into the byte at the address contained in ebx.
mov word [ebx], 2 ; Move the entire 2 represented in 16 bits into the 2 bytes
; starting from the address contained in ebx.
mov dword [ebx], 2 ; Move the entire 2 represented in 32 bits into the 4 bytes
; starting from the address contained in ebx.

Loop Instruction

The loop instruction is used for loops with a predetermined number of iterations, loaded into the ecx register. Its syntax is as follows:

mov ecx, 10 ; Initialize ecx with the number of iterations
label:
; loop content
loop label

At each iteration, the ecx register is decremented, and if it's not equal to 0, the execution jumps to the specified label. There are other forms of the instruction that additionally check the ZF flag:

MnemonicDescription
loope/loopz labelDecrement ecx, jump to label if ecx != 0 and ZF == 1
loopne/loopnz labelDecrement ecx, jump to label if ecx != 0 and ZF != 1

NOTE: When using jumps in an assembly language program, it's important to consider the difference between a short jump (near jump) and a long jump (far jump).

Type and exampleSize and significanceDescription
Short Jump (loop)2 bytes (one byte for the opcode and one for the address)The relative address of the instruction to which the jump is intended must not be more than 128 bytes away from the current instruction address.
Long Jump (jmp)3 bytes (one byte for the opcode and two for the address)The relative address of the instruction to which the jump is intended must not be more than 32768 bytes away from the current instruction address.